﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Globalization;

namespace Gmantis.Controls
{
    [TemplatePart(Name = "Hinting", Type = typeof(FrameworkElement)), TemplatePart(Name = "HintingCheckMark", Type = typeof(FrameworkElement))]
    public class ListBoxItem : ListViewerItem
    {
        // Fields
        internal FrameworkElement _elementHinting;
        internal FrameworkElement _elementHintingCheckMark;
        internal new bool _isLoaded;
        private bool _isSelected;
        internal const string HintingCheckMarkElementName = "HintingCheckMark";
        internal const string HintingElementName = "Hinting";
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(ListBoxItem), null);
        public static readonly DependencyProperty SelectedBackgroundProperty = DependencyProperty.Register("SelectedBackground", typeof(Brush), typeof(ListBoxItem), null);

        // Methods
        public ListBoxItem()
        {
            this.DefaultStyleKey = typeof(ListBoxItem);
        }

        private TranslateTransform GetHintingTransform()
        {
            TranslateTransform renderTransform = this._elementHinting.RenderTransform as TranslateTransform;
            if (renderTransform == null)
            {
                renderTransform = new TranslateTransform();
                this._elementHinting.RenderTransform = renderTransform;
            }
            return renderTransform;
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        internal void Hinting(Orientation orientation, double offset)
        {
            double num = 0.0;
            if (Math.Abs(offset) < 20.0)
                num = offset;
            else
                num = 20.0 * Math.Sign(offset);

            TranslateTransform hintingTransform = this.GetHintingTransform();
            if (orientation == Orientation.Vertical)
                hintingTransform.Y = num;
            else
                hintingTransform.X = num;

            this._elementHintingCheckMark.Opacity = 1.0;
        }

        private void OnAfterApplyTemplate()
        {
            this.UpdateSelectionStates(false);
        }

        public override void OnApplyTemplate()
        {
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            this._elementHinting = this.GetTemplateChild<FrameworkElement>("Hinting", true, ref errors);
            this._elementHintingCheckMark = this.GetTemplateChild<FrameworkElement>("HintingCheckMark", true, ref errors);
            if (!string.IsNullOrEmpty(errors))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to ListBoxItem.\nDetails: {0}", new object[] { errors }));
            }
            else
                this.OnAfterApplyTemplate();
        }

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            base.OnMouseEnter(e);
            VisualStateHelper.GoToState(this, "PointerOver", true);
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            base.OnMouseLeave(e);
            VisualStateHelper.GoToState(this, "Normal", true);
        }

        internal void StopHinting()
        {
            TranslateTransform hintingTransform = this.GetHintingTransform();
            hintingTransform.X = 0.0;
            hintingTransform.Y = 0.0;
            this._elementHintingCheckMark.Opacity = 0.0;
        }

        private void UpdateSelectionStates(bool useTransitions = true)
        {
            if (this.IsSelected)
                VisualStateHelper.GoToState(this, "Selected", useTransitions);
            else
                VisualStateHelper.GoToState(this, "NotSelected", useTransitions);
        }

        // Properties
        public bool IsSelected
        {
            get { return this._isSelected; }
            internal set
            {
                if (this._isSelected != value)
                {
                    this._isSelected = value;
                    this.UpdateSelectionStates(true);
                }
            }
        }

        public Brush MouseOverBrush
        {
            get { return (Brush)GetValue(MouseOverBrushProperty); }
            set { SetValue(MouseOverBrushProperty, value); }
        }

        public Brush SelectedBackground
        {
            get { return (Brush)GetValue(SelectedBackgroundProperty); }
            set { SetValue(SelectedBackgroundProperty, value); }
        }
    }
}
